package com.hollycrm.hollysqm.job.synchro;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.dangdang.ddframe.job.api.JobExecutionMultipleShardingContext;
import com.dangdang.ddframe.job.plugin.job.type.simple.AbstractSimpleElasticJob;
import com.hollycrm.hollysqm.job.synchro.dao.SynchroV8DataFileJobDao;
import com.hollycrm.hollysqm.util.Constant;
import com.hollycrm.hollysqm.util.GzipUtils;


/**
 * 同步存储过程，将V8接触记录数据定时抽取到质检表中
 * @author jianglong
 * @date 2017年2月23日 上午11:12:13
 */
@Service
public class SynchroV8DataFileJob extends AbstractSimpleElasticJob {

	private final Logger log = LoggerFactory.getLogger(getClass());
	
	private String dataFileDir;//已加载成功的文件夹
    private List<String> filePathList = new ArrayList<String>();//已加载的文件记录，不包含gz

    @Autowired
    private SynchroV8DataFileJobDao dao;
    
    /**
     * 是否准生产环境，执行不同的代码
     */
    @Value("${job.synchro.isProduce}")
    private String isProduce;
    /**
     * 数据包存放目录
     */
    @Value("${job.synchro.parentPath}")
    private String parentPath;
    /**
     * 入库表SQL
     */
    @Value("${job.synchro.contactInfoSql}")
    private String contactInfoSql;
    /**
     * 入库表SQL
     */
    @Value("${job.synchro.recordInfoSql}")
    private String recordInfoSql;
    /**
     * 入库表SQL
     */
    @Value("${job.synchro.serequestSql}")
    private String serequestSql;

    /**
     * job执行的主方法
     */
    @Override
    public void process(JobExecutionMultipleShardingContext shardingContext) {
        String areaCode = shardingContext.getJobParameter();//获取省份编号
        log.info("开始执行SynchroV8DataFileJob...");
        if (StringUtils.equals(isProduce, "true")) {
        	//取当前系统时间的前一个小时
            String currentTime = new SimpleDateFormat("yyyyMMddHH").format(DateUtils.addHours(new Date(), -1));
            this.produceProcess(areaCode, currentTime);//上生产环境代码
        } else {
            this.loadAllProcess(areaCode);//上生产环境调试数据代码,一次性加载所有数据
        }
        log.info("结束执行SynchroV8DataFileJob...");
    }

    /**
     * 生产方法，用于job实际生产环境执行;
     * @param areaCode    省份代码
     * @param currentTime 当前时间（小时）
     */
    public void produceProcess(String areaCode, String currentTime) {
        String excuteDate;
        try {
            excuteDate = this.fileLoad(currentTime);//加载文件，返回文件的业务执行时间
            log.info("执行时间：" + excuteDate);
            this.parseFileText(areaCode);//解析文件
//            this.deleteFileDir();//删除指定的文件夹
            if (StringUtils.isNotBlank(excuteDate)) {
//                dao.executePrc(excuteDate, areaCode);
            }
        } catch (Exception e) {
            log.error("SynchroV8DataFileJob执行异常！", e);
            e.printStackTrace();
        }
        this.clear();
    }

    /**
     * 测试方法，用于在job上线调试时，将指定目录下所有文件夹下的数据文件进行加载
     * @param areaCode 省份代码
     * @throws Exception
     */
    public void loadAllProcess(String areaCode) {
        File fileDir = new File(parentPath);
        if (!fileDir.exists()) {
            log.error("文件目录不存在！file path :" + parentPath);
            return;
        }
        File[] files = fileDir.listFiles(); 
        log.info("上传数据包目录共："+(files!=null?files.length:0)+"个");
        for (File file : files) {
            if (file.isDirectory()) {
            	log.info("本次加载数据包文件夹："+ file.getName());
                this.produceProcess(areaCode, file.getName());
            }
        }
    }

    /**
     * 指定目录,读取文件列表
     * @param currentTime 文件夹名称，当前小时：yyyyMMddHH
     * @throws Exception
     */
    public String fileLoad(String currentTime) throws Exception {
        File fileDir = new File(parentPath + currentTime + File.separator);
        if (!fileDir.exists()) {
            throw new Exception("文件目录不存在！file path :" + parentPath + currentTime);
        }
        File[] files = fileDir.listFiles();
        if (files.length <= 0) {
            log.info("未获取任何文件，文件目录为空！file path :" + parentPath + currentTime);
            return null;
        }
        dataFileDir = fileDir.getPath();
        String filePath;
        String fileName = "";
        try {
            for (File file : files) {
                filePath = file.getPath();
                log.info("加载文件:" + filePath);
                if (filePath.lastIndexOf(File.separator) == -1) {
                    log.error("获取的文件路径不合法！file path:" + filePath);
                    //抛出异常，存在非法文件
                    throw new Exception("获取的文件路径不合法！file path:" + filePath);
                }
                fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
                //_R_：表示重传标识，首次上传不需要标识。
                if (fileName.contains("_R_")) {
                    continue;
                }
                //存在.gz压缩包，需解压文件
                if (fileName.endsWith(".gz")) {
                    filePath = GzipUtils.doUncompressFile(filePath);
                    log.info("gz解压后的文件:" + filePath);
                }
                filePathList.add(filePath);
            }
        } catch (Exception e) {
            log.info("加载文件异常！", e);
            throw e;
        }
        return getExcuteDate(fileName);
    }

    /**
     * 文本内容抽取
     * @param areaCode 省份编码
     * @throws Exception
     */
    public void parseFileText(String areaCode) throws Exception {
        if (filePathList.size() <= 0) {
            log.info("未获取任何文件，文件列表为空！");
            return;
        }
        File file;
        String fileType;
        String fileName;
        for (String filePath : filePathList) {
            //获取文件类型，如：文件名：RECOINFO_2015111116_74_00017.txt，获取的类型为RECOINFO
            fileName = filePath.substring(filePath.lastIndexOf(File.separator) + 1);
            fileType = fileName.substring(0, fileName.indexOf("_"));
            file = new File(filePath);
            System.out.println("已处理："+file.getParent());
//            insertData(areaCode, fileType, FileUtils.readLines(file, "UTF-8"));
//            FileUtils.deleteQuietly(file);//删除文件
        }
    }

    /**
     * 解析文本数据，并插入对应表中
     *
     * @param areaCode 省份编码
     * @param fileType 文件类型：CUSTCONTINFO、RECOINFO、RECOINFO
     * @param dataList 数据集
     * @throws Exception
     */
    public void insertData(String areaCode, String fileType, List<String> dataList) throws Exception {
        dataList.remove(0);//删除第一行头记录,非标准表记录格式
        if (Constant.JOB_SYNCHRO_CUSTCONTINFO.equalsIgnoreCase(fileType)) {
            dao.insertCustcontinfoData(areaCode, contactInfoSql, dataList);
        } else if (Constant.JOB_SYNCHRO_RECOINFO.equalsIgnoreCase(fileType)) {
            dao.insertRecoinfoData(areaCode, recordInfoSql, dataList);
        } else if (Constant.JOB_SYNCHRO_SEREQUEST.equalsIgnoreCase(fileType)) {
            dao.insertSerequestfoData(areaCode, serequestSql, dataList);
        } else {
            throw new Exception("未获取指定类型的文本文件！文件名称必需包含CUSTCONTINFO、RECOINFO、RECOINFO等字符");
        }
    }

    /**
     * 删除指定文件夹
     */
    public void deleteFileDir() throws Exception {
        if (StringUtils.isNotBlank(dataFileDir)) {
            File fileObj;
            try {
                fileObj = new File(dataFileDir);
                if (fileObj.exists()) {
                    FileUtils.deleteDirectory(fileObj);
                }
            } catch (Exception e) {
                log.info("文件删除失败！");
                throw e;
            }
        }
    }

    /**
     * 清空对象
     */
    public void clear() {
        dataFileDir = null;
        if (filePathList != null) {
            filePathList.clear();
        }
    }

    /**
     * 截取文件名中的执行时间
     * @param fileName 文件名称
     * @return
     */
    public String getExcuteDate(String fileName) {
        if (fileName.indexOf("_") != -1) {
            int index = fileName.indexOf("_");
            fileName = fileName.substring(index + 1);
            index = fileName.indexOf("_");
            return index != -1 ? fileName.substring(0, index) : fileName;
        }
        return fileName;
    }
	
}
